package org.fast.cms.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.fast.cms.common.utils.CacheUtils;
import org.fast.cms.common.utils.SpringUtils;
import org.fast.cms.common.utils.string.StringUtils;
import org.fast.cms.domain.admin.response.menu.Menu;
import org.fast.cms.domain.admin.response.user.User;
import org.fast.cms.entity.admin.SysMenu;
import org.fast.cms.entity.admin.SysRole;
import org.fast.cms.entity.admin.SysUser;
import org.fast.cms.enums.BusinessTypeEnum;
import org.fast.cms.security.LoginUserInfo;
import org.fast.cms.security.enums.DataScope;
import org.fast.cms.service.admin.SysMenuService;
import org.fast.cms.service.admin.SysRoleService;
import org.fast.cms.service.admin.SysUserService;
import org.springframework.beans.BeanUtils;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/** 
* @author weigen.ye 
* @date 创建时间：2017年6月17日 下午1:04:59 
*
*/

public class UserUtils {
	
	private static List<Integer> typeList = Lists.newArrayList();
	static {
		typeList.add(5);
		typeList.add(6);
		typeList.add(8);
		typeList.add(9);
		typeList.add(10);
		typeList.add(11);
	}

	private static SysUserService userService = SpringUtils.getBean(SysUserService.class);
	private static SysMenuService menuService = SpringUtils.getBean(SysMenuService.class);
	private static SysRoleService roleService = SpringUtils.getBean(SysRoleService.class);

	private static final String USER_CACHE = "userCache";
	private static final String USER_CACHE_ID_ = "id_";
	private static final String USER_CACHE_LOGIN_NAME_ = "ln_";
	private static final String USER_CACHE_DATA_ = "data_";

	private static final String SESSION_ROLE_LIST = "roleList";
	private static final String SESSION_MENU_LIST = "menuList";

	/**
	 * 根据用户名取得用户
	 * 
	 * @param userCode
	 * @return
	 */
	public static SysUser get(int userId) {
		if (userId == 0)
			return new SysUser();
		SysUser user = (SysUser) CacheUtils.get(USER_CACHE, USER_CACHE_ID_ + userId);
		if (user == null) {
			user = userService.getUserById(userId);
			if (user != null) {
				saveUserCache(user);
			} else {
				return new SysUser();
			}
		}
		return user;
	}
	
	/**
	 * 通过用户名取得用户ID
	 * @param userName
	 * @return
	 */
	public static Integer[] getUserIdByName(String userName) {
		return userService.getUserIdByName(userName);
	}

	/**
	 * 根据登录名获取用户
	 * 
	 * @param loginName
	 */
	public static SysUser getByLoginName(String loginName) {
		SysUser user = (SysUser) CacheUtils.get(USER_CACHE,
				USER_CACHE_LOGIN_NAME_ + loginName );
		if (user == null) {
			user = userService.getUserByLoginName(loginName);
			if (user != null) {
				saveUserCache(user);
			}
		}
		return user;
	}
	
	public static void clearLoginCache(String loginName){
		CacheUtils.remove(USER_CACHE, getUserNameCacheKey(loginName));
	}

	/**
	 * 删除缓存内容
	 * 
	 * @param user
	 */
	public static void clearCache(LoginUserInfo user) {
		CacheUtils.remove(USER_CACHE, USER_CACHE_ID_ + user.getUserId());
		CacheUtils.remove(USER_CACHE, getUserNameCacheKey(user.getLoginName()));
	}

	/**
	 * 删除Session内容
	 */
	public static void clearSession() {
		removeSession(SESSION_MENU_LIST);
		removeSession(SESSION_ROLE_LIST);
		User user = getUser();
		CacheUtils.remove(USER_CACHE, USER_CACHE_DATA_ + user.getUserId());
		CacheUtils.remove(USER_CACHE, getUserNameCacheKey(user.getUserName()));
	}

	/**
	 * 清除当前用户缓存
	 * 
	 * @param user
	 */
	public static void clearCache(SysUser user) {
		if (user != null) {
			CacheUtils.remove(USER_CACHE, USER_CACHE_ID_ + user.getUserId());
			CacheUtils.remove(USER_CACHE, getUserNameCacheKey(user.getLoginName()));
		}
	}

	private static String getUserNameCacheKey(String loginName) {
		return USER_CACHE_LOGIN_NAME_ + loginName;
	}
    
	/**
	 * 获取用户可以操作的管理后台目录
	 * @return
	 */
	public static List<Menu> getMenuTree(){
		List<Menu> result=new ArrayList<Menu>();
		User user=getUser();
		if(user.getMenuList()!=null){
			result=user.getMenuList();
		}
		return result;
	}
	
	/**
	 * 取得当前登录用户信息
	 * 
	 * @return
	 */
	public static User getUser() {
		LoginUserInfo userInfo = getLoginUserInfo();
		if (userInfo != null) {
			User user = (User) CacheUtils.get(USER_CACHE, USER_CACHE_DATA_ + userInfo.getUserId());
			if (user == null) {
				SysUser sysUser = getByLoginName(userInfo.getLoginName());
				user = new User();
				if (sysUser != null) {
					BeanUtils.copyProperties(sysUser, user);
					List<SysRole> roleList = getRoleList();
					if (roleList.size() > 0) {
						SysRole role = roleList.get(0);
						// 设置数据权限范围
						user.setDataScope(role.getDataScope());
						user.setAdmin(role.getIsAdmin().intValue() == 1);
						user.setRoleType(role.getType());
					} else {
						user.setDataScope(DataScope.OWN_DATA.getType());
						user.setAdmin(false);
					}

					// 设置用户菜单权限
					user.setMenuList(menuService.getMenuTree(getMenuList()));
					
					Map<String, Integer> permissions = Maps.newHashMap();					
					Set<String> apiList = Sets.newHashSet();
					List<SysMenu> lisMenu = getMenuList();
					for (SysMenu m : lisMenu) {
						if (StringUtils.isNotBlank(m.getPermission())) {
							permissions.put(m.getPermission(), 1);
							apiList.add(m.getHref());
						}
					}
					user.setPermission(permissions);
					user.setApiList(apiList);
				}
				CacheUtils.put(USER_CACHE, USER_CACHE_DATA_ + userInfo.getUserId(), user);
			}
			return user;
		}
		return new User();
	}

	/**
	 * 取得登录用户信息
	 * 
	 * @return
	 */
	public static LoginUserInfo getLoginUserInfo() {
		Subject subject = SecurityUtils.getSubject();
		LoginUserInfo userInfo = (LoginUserInfo) subject.getPrincipal();
		if (userInfo != null) {
			return userInfo;
		}
		return null;
	}

	/**
	 * 保存用户信息到缓存
	 * 
	 * @param user
	 */
	public static void saveUserCache(SysUser user) {
		if (user != null) {
			if (user.getUserId() != null) {
				CacheUtils.put(USER_CACHE, USER_CACHE_ID_ + user.getUserId(), user);
			}
			if (StringUtils.isNotBlank(user.getLoginName())) {
				CacheUtils.put(USER_CACHE, getUserNameCacheKey(user.getLoginName()), user);
			}
		}
	}

	/**
	 * session中读取菜单列表
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static List<SysMenu> getMenuList() {
		List<SysMenu> menuList = (List<SysMenu>) getSession(SESSION_MENU_LIST);
		if (menuList == null) {
			LoginUserInfo user = getLoginUserInfo();
			if (user != null) {
				menuList = menuService.getMenuActionByUserId(user.getUserId());
				putSession(SESSION_MENU_LIST, menuList);
			}
		}
		return menuList;
	}

	@SuppressWarnings("unchecked")
	public static List<SysRole> getRoleList() {
		List<SysRole> roleList = (List<SysRole>) getSession(SESSION_ROLE_LIST);

		if (roleList == null) {
			LoginUserInfo user = getLoginUserInfo();
			roleList = roleService.getUserRole(user.getUserId());
			putSession(SESSION_ROLE_LIST, roleList);
		}
		return roleList;
	}

	// session start
	/**
	 * 从Session中取值
	 * 
	 * @param key
	 * @return
	 */
	public static Object getSession(String key) {
		return getSession(key, null);
	}

	/**
	 * 从Session中取值
	 * 
	 * @param key
	 * @param defaultValue
	 * @return
	 */
	public static Object getSession(String key, Object defaultValue) {
		Object obj = getSession().getAttribute(key);
		return obj == null ? defaultValue : obj;
	}

	/**
	 * 保存到Session
	 * 
	 * @param key
	 * @param value
	 */
	public static void putSession(String key, Object value) {
		getSession().setAttribute(key, value);
	}

	/**
	 * Session移除
	 * 
	 * @param key
	 */
	public static void removeSession(String key) {
		getSession().removeAttribute(key);
	}

	/**
	 * 取得Shiro Session
	 * 
	 * @return
	 */
	public static Session getSession() {
		Subject subject = SecurityUtils.getSubject();
		Session session = subject.getSession(false);
		if (session == null) {
			session = subject.getSession();
		}
		return session;
	}

	// session end

	/**
	 * 根据业务类型取得权限SQL
	 * 
	 * @param type
	 * @return
	 */
	public static String getScopeSql(BusinessTypeEnum type) {
		User user = getUser();
		if (user.getDataScope() == DataScope.ALL.getType())
			return null;
        return "";
	}
}
